module Memory(
  input enable,
  output ready,

//memory interface
  output dcache_ren,
  output [63:0] dcache_raddr,
  output [3:0] dcache_rsize,
  input [63:0] dcache_rdata, 
  input [3:0] dcache_rbytes, 
  input dcache_rdata_valid,
  input dcache_rbusy,

  output dcache_wen,
  output [63:0] dcache_waddr,
  output [63:0] dcache_wdata, 
  output [3:0] dcache_wsize,
  input dcache_wbusy,
  

//from execute stage
  input [31:0] inst_i,
  input [63:0] pc_i,
  input difftest_raise_hard_intr_i,
  input [1:0] other_op_i,

  input load_valid,
  input [63:0] load_addr,
  input [3:0] load_bytes,
  input load_sign,

  input store_valid,
  input [63:0] store_addr,
  input [63:0] store_data,
  input [3:0] store_bytes,

  input [4:0] dest_i,
  input [63:0] dest_data_i,
  input dest_valid_i,
//to writeback stage
  output [1:0] other_op_o,
  output [31:0] inst_o,
  output [63:0] pc_o,
  output difftest_raise_hard_intr_o,
  output difftest_memory_op_o,
  output [63:0] difftest_memory_addr_o,

  output [63:0] load_data_o,
  output load_valid_o,

  output [63:0] dest_data_o,
  output [4:0] dest_o,
  output dest_valid_o

);
  assign pc_o = pc_i;
  assign inst_o = inst_i;
  assign other_op_o = other_op_i;
  assign difftest_memory_op_o = load_valid|store_valid;
  assign difftest_memory_addr_o = {64{load_valid}}&load_addr|{64{store_valid}}&store_addr;
  assign difftest_raise_hard_intr_o = difftest_raise_hard_intr_i;
  assign dcache_ren = load_valid;
  assign dcache_raddr = load_addr;

  wire [63:0] rdata = dcache_rdata;

  wire [63:0] dest_data_signed    = {64{dcache_rbytes[0]}}&{{56{rdata[ 7]}},rdata[ 7:0]} |
                                    {64{dcache_rbytes[1]}}&{{48{rdata[15]}},rdata[15:0]} |
                                    {64{dcache_rbytes[2]}}&{{32{rdata[31]}},rdata[31:0]} |
                                    {64{dcache_rbytes[3]}}&{rdata[63:0]};
  wire [63:0] dest_data_unsigned  = {64{dcache_rbytes[0]}}&{56'b0,rdata[ 7:0]} |
                                    {64{dcache_rbytes[1]}}&{48'b0,rdata[15:0]} |
                                    {64{dcache_rbytes[2]}}&{32'b0,rdata[31:0]} |
                                    {64{dcache_rbytes[3]}}&{rdata[63:0]};
  assign dest_data_o = {64{dest_valid_i}}&dest_data_i;

  assign dcache_wen = store_valid;
  assign dcache_waddr = store_addr;
  assign dcache_wdata = store_data; 
  assign dcache_wsize = store_bytes;
  assign dcache_rsize = load_bytes;
  assign dest_o = dest_i;
  assign dest_valid_o = dest_valid_i;

  assign load_valid_o = load_valid;
  assign load_data_o = {64{load_sign}}&dest_data_signed | {64{!load_sign}}&dest_data_unsigned;
  assign ready = enable&(~(dcache_rbusy|dcache_wbusy));
endmodule
